﻿using System;
using System.Text;
using System.Runtime.InteropServices;

/*
 * Useful P/Invoke definitions for Crypto API functions and structures
 */

public class Capi
{
   [DllImport("cryptui.dll", CharSet = CharSet.Unicode, SetLastError = true)]
   public static extern IntPtr CryptUIDlgSelectCertificateFromStore(
     IntPtr hCertStore,
     IntPtr hwnd,
     string pwszTitle,
     string pwszDisplayString,
     UInt32 dwDontUseColumn,
     UInt32 dwFlags,
     IntPtr pvReserved
   );

   [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   public static extern Boolean CertGetCertificateContextProperty(
      IntPtr pCertCtx,
      CertPropID dwPropID,
     [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] [In, Out]
          byte[] pbData,
      ref UInt32 pcbData);

   [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   public static extern Boolean CertFreeCertificateContext(
      IntPtr pCertContext
   );

   [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   public static extern Boolean CryptBinaryToString(
     [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] [In]
     byte[] pbBinary,
     UInt32 cbBinary,
     CryptStringFlags dwFlags,
     StringBuilder pszString,
     ref UInt32 pcchString
   );


   [DllImport("advapi32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
   public static extern Boolean CryptEnumProviders(
       UInt32 dwIndex,
       IntPtr pdwReserved,
       UInt32 dwFlags,
       ref UInt32 pdwProvType,
       StringBuilder pszProvName,
       ref UInt32 pcbProvName);

   [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   public static extern Boolean CryptAcquireContext(
       ref IntPtr hProv,
       string pszContainer,
       string pszProvider,
       ProviderType dwProvType,
       ContextFlags dwFlags);

   [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   public static extern Boolean CryptReleaseContext(
       IntPtr hProv,
       UInt32 dwFlags);

   [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   public static extern Boolean CryptGetUserKey(
     IntPtr hProv,
     KeySpecType dwKeySpec,
     ref  IntPtr phUserKey
   );
   [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   public static extern Boolean CryptDestroyKey(
      IntPtr  hKey
   );





   [DllImport("crypt32.dll", SetLastError = true)]
   public static extern IntPtr CertCreateSelfSignCertificate(
       IntPtr hProv,
       ref CRYPTOAPI_BLOB pSubjectIssuerBlob,
       UInt32 dwFlags,
       ref CRYPT_KEY_PROV_INFO pKeyProvInfo,
       IntPtr pSignatureAlgorithm,
       IntPtr pStartTime,
       IntPtr pEndTime,
       IntPtr pExtensions);

   [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   public static extern Boolean CertStrToName(
      CertEncodingType dwCertEncodingType,
      string pszX500,
      CertNameFlags dwStrType,
      IntPtr pvReserved,
      byte[] pbEncoded,
      ref int pcbEncoded,
      IntPtr ppszError);

   [DllImport("crypt32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
   public static extern Boolean PFXExportCertStoreEx(
      IntPtr hStore,
      ref  CRYPTOAPI_BLOB pPFX,
      string szPassword,
      IntPtr pvReserved,
      PfxExportFlags dwFlags
   );

   [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   public static extern IntPtr CertOpenStore(
     CertStoreType lpszStoreProvider,
     CertEncodingType dwMsgAndCertEncodingType,
     IntPtr hCryptProv,
     UInt32 dwFlags,
     IntPtr pvPara
   );
   [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   public static extern Boolean CertCloseStore(
     IntPtr hCertStore,
     UInt32 dwFlags
   );

   [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   public static extern Boolean CertAddCertificateContextToStore(
     IntPtr hCertStore,
     IntPtr pCertContext,
     CertAddDisposition dwAddDisposition,
     IntPtr ppStoreContext
   );

   public enum KeySpecType : uint
   {
      AT_KEYEXCHANGE          = 1,
      AT_SIGNATURE            = 2,
   }

   public enum ProviderType : uint
   {
      PROV_NONE = 0,
      PROV_RSA_FULL = 1,
      PROV_RSA_SIG = 2,
      PROV_DSS = 3,
      PROV_FORTEZZA = 4,
      PROV_MS_EXCHANGE = 5,
      PROV_SSL = 6,
      PROV_RSA_SCHANNEL = 12,
      PROV_DSS_DH = 13,
      PROV_EC_ECDSA_SIG = 14,
      PROV_EC_ECNRA_SIG = 15,
      PROV_EC_ECDSA_FULL = 16,
      PROV_EC_ECNRA_FULL = 17,
      PROV_DH_SCHANNEL = 18,
      PROV_SPYRUS_LYNKS = 20,
      PROV_RNG = 21,
      PROV_INTEL_SEC = 22,
      PROV_REPLACE_OWF = 23,
      PROV_RSA_AES = 24,
   }

   public enum CertAddDisposition : uint
   {
      CERT_STORE_ADD_NEW                                  = 1,
      CERT_STORE_ADD_USE_EXISTING                         = 2,
      CERT_STORE_ADD_REPLACE_EXISTING                     = 3,
      CERT_STORE_ADD_ALWAYS                               = 4,
      CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES  = 5,
      CERT_STORE_ADD_NEWER                                = 6,
      CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES             = 7,
   }

   public enum CertStoreType : uint
   {
      CERT_STORE_PROV_MSG                 = 1,
      CERT_STORE_PROV_MEMORY              = 2,
      CERT_STORE_PROV_FILE                = 3,
      CERT_STORE_PROV_REG                 = 4,

      CERT_STORE_PROV_PKCS7               = 5,
      CERT_STORE_PROV_SERIALIZED          = 6,
      CERT_STORE_PROV_FILENAME_A          = 7,
      CERT_STORE_PROV_FILENAME_W          = 8,
      CERT_STORE_PROV_FILENAME            = CERT_STORE_PROV_FILENAME_W,
      CERT_STORE_PROV_SYSTEM_A            = 9,
      CERT_STORE_PROV_SYSTEM_W            = 10,
      CERT_STORE_PROV_SYSTEM              = CERT_STORE_PROV_SYSTEM_W,
   }

   [Flags]
   public enum PfxExportFlags : uint
   {
      REPORT_NO_PRIVATE_KEY                   = 0x0001,
      REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY   = 0x0002,
      EXPORT_PRIVATE_KEYS                     = 0x0004,
      PKCS12_INCLUDE_EXTENDED_PROPERTIES      = 0x0010,
   }

   [Flags]
   public enum CertNameFlags : uint
   {
      CERT_SIMPLE_NAME_STR        = 1,
      CERT_OID_NAME_STR           = 2,
      CERT_X500_NAME_STR          = 3,
      CERT_XML_NAME_STR           = 4,

      //+-------------------------------------------------------------------------
      //  Certificate name string type flags OR'ed with the above types
      //--------------------------------------------------------------------------
      CERT_NAME_STR_SEMICOLON_FLAG    = 0x40000000,
      CERT_NAME_STR_NO_PLUS_FLAG      = 0x20000000,
      CERT_NAME_STR_NO_QUOTING_FLAG   = 0x10000000,
      CERT_NAME_STR_CRLF_FLAG         = 0x08000000,
      CERT_NAME_STR_COMMA_FLAG        = 0x04000000,
      CERT_NAME_STR_REVERSE_FLAG      = 0x02000000,
      CERT_NAME_STR_FORWARD_FLAG      = 0x01000000,

      CERT_NAME_STR_DISABLE_IE4_UTF8_FLAG     = 0x00010000,
      CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG   = 0x00020000,
      CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG  = 0x00040000,
      CERT_NAME_STR_FORCE_UTF8_DIR_STR_FLAG   = 0x00080000,
      CERT_NAME_STR_DISABLE_UTF8_DIR_STR_FLAG = 0x00100000,
      CERT_NAME_STR_ENABLE_PUNYCODE_FLAG      = 0x00200000,
   }


   [Flags]
   public enum CryptStringFlags : uint
   {
      CRYPT_STRING_BASE64HEADER = 0x00000000,
      CRYPT_STRING_BASE64 = 0x00000001,
      CRYPT_STRING_BINARY = 0x00000002,
      CRYPT_STRING_BASE64REQUESTHEADER = 0x00000003,
      CRYPT_STRING_HEX = 0x00000004,
      CRYPT_STRING_HEXASCII = 0x00000005,
      CRYPT_STRING_BASE64_ANY = 0x00000006,
      CRYPT_STRING_ANY = 0x00000007,
      CRYPT_STRING_HEX_ANY = 0x00000008,
      CRYPT_STRING_BASE64X509CRLHEADER = 0x00000009,
      CRYPT_STRING_HEXADDR = 0x0000000a,
      CRYPT_STRING_HEXASCIIADDR = 0x0000000b,
      CRYPT_STRING_HEXRAW = 0x0000000c,

      CRYPT_STRING_HASHDATA = 0x10000000,
      CRYPT_STRING_STRICT = 0x20000000,
      CRYPT_STRING_NOCRLF = 0x40000000,
      CRYPT_STRING_NOCR = 0x80000000,
   }

   [Flags]
   public enum ContextFlags : uint
   {
      CRYPT_VERIFYCONTEXT = 0xF0000000,
      CRYPT_NEWKEYSET = 0x00000008,
      CRYPT_DELETEKEYSET = 0x00000010,
      CRYPT_MACHINE_KEYSET = 0x00000020,
      CRYPT_SILENT = 0x00000040,
      CRYPT_DEFAULT_CONTAINER_OPTIONAL = 0x00000080,
   }

   public enum CertPropID : uint
   {
      CERT_KEY_PROV_HANDLE_PROP_ID = 1,
      CERT_KEY_PROV_INFO_PROP_ID = 2,
      CERT_SHA1_HASH_PROP_ID = 3,
      CERT_MD5_HASH_PROP_ID = 4,
      CERT_HASH_PROP_ID = CERT_SHA1_HASH_PROP_ID,
      CERT_KEY_CONTEXT_PROP_ID = 5,
      CERT_KEY_SPEC_PROP_ID = 6,
      CERT_IE30_RESERVED_PROP_ID = 7,
      CERT_PUBKEY_HASH_RESERVED_PROP_ID = 8,
      CERT_ENHKEY_USAGE_PROP_ID = 9,
      CERT_CTL_USAGE_PROP_ID = CERT_ENHKEY_USAGE_PROP_ID,
      CERT_NEXT_UPDATE_LOCATION_PROP_ID = 10,
      CERT_FRIENDLY_NAME_PROP_ID = 11,
      CERT_PVK_FILE_PROP_ID = 12,
      CERT_DESCRIPTION_PROP_ID = 13,
      CERT_ACCESS_STATE_PROP_ID = 14,
      CERT_SIGNATURE_HASH_PROP_ID = 15,
      CERT_SMART_CARD_DATA_PROP_ID = 16,
      CERT_EFS_PROP_ID = 17,
      CERT_FORTEZZA_DATA_PROP_ID = 18,
      CERT_ARCHIVED_PROP_ID = 19,
      CERT_KEY_IDENTIFIER_PROP_ID = 20,
      CERT_AUTO_ENROLL_PROP_ID = 21,
      CERT_PUBKEY_ALG_PARA_PROP_ID = 22,
      CERT_CROSS_CERT_DIST_POINTS_PROP_ID = 23,
      CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID = 24,
      CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID = 25,
      CERT_ENROLLMENT_PROP_ID = 26,
      CERT_DATE_STAMP_PROP_ID = 27,
      CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID = 28,
      CERT_SUBJECT_NAME_MD5_HASH_PROP_ID = 29,
      CERT_EXTENDED_ERROR_INFO_PROP_ID = 30,

      // Note, 32 - 35 are reserved for the CERT, CRL, CTL and KeyId file element IDs.
      //       36 - 63 are reserved for future element IDs.

      CERT_RENEWAL_PROP_ID = 64,
      CERT_ARCHIVED_KEY_HASH_PROP_ID = 65,
      CERT_AUTO_ENROLL_RETRY_PROP_ID = 66,
      CERT_AIA_URL_RETRIEVED_PROP_ID = 67,
      // Note, 68 - 70 are reserved for future use.
      CERT_REQUEST_ORIGINATOR_PROP_ID = 71,
      CERT_FIRST_RESERVED_PROP_ID = 72,

      CERT_LAST_RESERVED_PROP_ID = 0x00007FFF,
      CERT_FIRST_USER_PROP_ID = 0x00008000,
      CERT_LAST_USER_PROP_ID = 0x0000FFFF,
   }

   public enum CertStoreDisposition : uint
   {
      CERT_STORE_ADD_NEW = 1,
      CERT_STORE_ADD_USE_EXISTING = 2,
      CERT_STORE_ADD_REPLACE_EXISTING = 3,
      CERT_STORE_ADD_ALWAYS = 4,
      CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES = 5,
      CERT_STORE_ADD_NEWER = 6,
      CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES = 7
   }

   [Flags]
   public enum CertEncodingType : uint
   {
      X509_ASN_ENCODING = 0x00000001,
      PKCS_7_ASN_ENCODING = 0x00010000,
   }
   
   [Flags]
   public enum KeyFlags : uint
   {
      CERT_SET_KEY_PROV_HANDLE_PROP_ID = 1,
      CRYPT_MACHINE_KEYSET = 32,
      CRYPT_SILENT = 64,
   }

   [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
   public struct CERT_EXTENSION
   {
      [MarshalAs(UnmanagedType.LPTStr)]
      public string pszObjId;
      [MarshalAs(UnmanagedType.Bool)]
      public Boolean fCritical;
      public int cbData;
      public IntPtr pbData;
   }

   [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
   public struct CERT_EXTENSIONS
   {
      public int cExtension;
      public IntPtr rgExtension;
   }

   [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
   public struct CRYPTOAPI_BLOB
   {
      public int cbData;
      public IntPtr pbData;
   }

   [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
   public struct CRYPT_KEY_PROV_PARAM
   {
      public UInt32 dwParam;
      [MarshalAs(UnmanagedType.LPArray,
            SizeParamIndex = 2,
            ArraySubType = UnmanagedType.U1)]
      public byte[] pbData;
      public UInt32 cbData;
      public UInt32 dwFlags;
   }

   [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
   public struct CRYPT_KEY_PROV_INFO
   {
      [MarshalAs(UnmanagedType.LPWStr)]
      public string pwszContainerName;
      [MarshalAs(UnmanagedType.LPWStr)]
      public string pwszProvName;
      public UInt32 dwProvType;
      public UInt32 dwFlags;
      public int cProvParam;
      public IntPtr rgProvParam;
      public UInt32 dwKeySpec;
   }
}
